<template>
    <div class="top-container">
        <el-row :gutter="20">
            <el-col :sm="7" :lg="5" :xl="4">
                <el-col :sm="8" :lg="8" :xl="8">
                    <file-upload
                            class="btn-file-upload"
                            ref="upload"
                            :name="uploadConfig.name"
                            v-model="uploadConfig.files"
                            :multiple="uploadConfig.multiple"
                            :directory="uploadConfig.directory"
                            :drop="uploadConfig.drop"
                            :drop-directory="uploadConfig.dropDirectory"
                            :post-action="uploadConfig.postAction"
                            :uploadAuto="uploadConfig.uploadAuto"
                            :thread="uploadConfig.thread"
                            :data="uploadConfig.data"
                            :extensions="uploadConfig.extensions"
                            @input-file="inputFile"
                            @input-filter="inputFilter">
                        <!--<el-dropdown split-button type="primary" style="z-index: 1000">-->
                        <!--选择文件-->
                        <!--<el-dropdown-menu slot="dropdown">-->
                        <!--<el-dropdown-item>添加文件</el-dropdown-item>-->
                        <!--<el-dropdown-item>添加文件夹</el-dropdown-item>-->
                        <!--</el-dropdown-menu>-->
                        <!--</el-dropdown>-->
                        <el-button type="primary">
                            选择文件
                        </el-button>
                    </file-upload>
                </el-col>
                <el-col :sm="12" :lg="4" :xl="4" v-if="false">
                    <el-button @click.prevent="handleSelectFolader">选择文件夹</el-button>
                </el-col>
            </el-col>
            <el-col :sm="12" :lg="16" :xl="18">
                <el-button v-if="!$refs.upload || !$refs.upload.active" @click.prevent="$refs.upload.active = true"
                           icon="el-icon-upload">
                    开始上传
                </el-button>
                <el-button v-else @click.prevent="$refs.upload.active = false">
                    停止上传
                </el-button>
                <el-button icon="el-icon-search" @click.prevent="historyDialogVisible = true">
                    历史查询
                </el-button>
                <el-button icon="el-icon-refresh" @click.prevent="reload()">
                    重置
                </el-button>
            </el-col>
            <el-col :sm="5" :lg="3" :xl="1" style="text-align: right">
                <el-button icon="el-icon-setting" @click.prevent="fileConfigDialogVisible = true">
                    文件配置管理
                </el-button>
            </el-col>
        </el-row>


        <div v-show="$refs.upload && $refs.upload.dropActive" class="drop-active">
            <h3>拖拽文件添加到上传队列</h3>
        </div>
        <el-table :data="uploadConfig.files" style="width: 100%" :row-key="rowKey" :expand-row-keys="expandRowkeys"
                  @expand-change="handleExpandChange">
            <el-table-column type="expand">
                <template slot-scope="props">
                    <el-row>
                        <el-steps :space="200" :active="socketData.stepActive" finish-status="success">
                            <el-step :title="item" v-for="item in collectionData.steps"></el-step>
                        </el-steps>
                    </el-row>
                    <el-row class="detail-context">
                        <el-col :span="10">
                            <el-form label-position="left">
                                <!--<el-form-item label="文件名称">-->
                                <!--<span>{{ props.row.name }}</span>-->
                                <!--</el-form-item>-->
                                <el-form-item label="总记录数">
                                    <span>{{ socketData.total }}</span>
                                </el-form-item>
                            </el-form>
                            <el-progress type="circle" :percentage="socketData.progress">
                                处理进度:{{socketData.progress}}%
                            </el-progress>
                        </el-col>
                        <el-col :span="14" class="right-context">
                            <el-row class="right-context-row">
                                处理监控<i class="el-icon-d-arrow-right"/>
                                <el-button type="text" v-if="dealOverDataCache.indexOf(props.row.name) > -1" @click.prevent="handleSeeDealDetail(props.row)">查看详情</el-button>
                                <el-button type="text" v-if="dealOverDataCache.indexOf(props.row.name) > -1 && socketData.successNum > 0"
                                           icon="el-icon-download" style="color: green"
                                           @click.prevent="handleDownloadInfo(props.row,dataSign.success)">导出成功信息</el-button>
                                <el-button type="text" v-if="dealOverDataCache.indexOf(props.row.name) > -1 && socketData.errorNum > 0"
                                           icon="el-icon-download" style="color: red"
                                           @click.prevent="handleDownloadInfo(props.row,dataSign.error)">导出失败信息</el-button>
                            </el-row>
                            <el-row class="right-context-row">
                                <span>等待处理: {{socketData.waitNum}}</span>
                                <el-progress :text-inside="true" :stroke-width="18" :percentage="socketData.wait"
                                             color="#8e71c7"></el-progress>
                            </el-row>
                            <el-row class="right-context-row">
                                <span>处理完成: {{socketData.successNum}}</span>
                                <el-progress :text-inside="true" :stroke-width="18" :percentage="socketData.success"
                                             status="success"></el-progress>
                            </el-row>
                            <el-row class="right-context-row">
                                <span>处理失败: {{socketData.errorNum}}</span>
                                <el-progress :text-inside="true" :stroke-width="18" :percentage="socketData.error"
                                             status="exception"></el-progress>
                            </el-row>
                        </el-col>
                    </el-row>
                </template>
            </el-table-column>
            <el-table-column label="文件名" prop="name" width="500"></el-table-column>
            <el-table-column label="大小" prop="size">
                <template slot-scope="scope">
                    {{scope.row.size | formatSize}}
                </template>
            </el-table-column>
            <el-table-column label="上传速度" prop="speed">
                <template slot-scope="scope">
                    {{scope.row.speed | formatSize}}
                </template>
            </el-table-column>
            <el-table-column label="状态" prop="status">
                <template slot-scope="scope">
                    <el-tag type="danger" v-if="scope.row.error">{{scope.row.error}}</el-tag>
                    <template v-else-if="scope.row.success">
                        <el-tag type="success">上传完成</el-tag>
                        <!-- 目前的实现结构对以下方式不支持 -->
                        <!--<el-tag type="success" v-if="dealOverDataCache.indexOf(scope.row.name) > -1">后台处理完成</el-tag>-->
                        <!--<el-tag type="warning" v-else>后台处理中...</el-tag>-->
                    </template>
                    <el-tag type="warning" v-else-if="scope.row.active">上传中...</el-tag>
                    <el-tag type="info" v-else>等待</el-tag>
                </template>
            </el-table-column>
            <el-table-column label="操作">
                <template slot-scope="scope">
                    <el-button v-if="scope.row.active" type="text"
                               @click.prevent="scope.row.active ? $refs.upload.update(scope.row, {error: 'cancel'}) : false">
                        取消上传
                    </el-button>
                    <el-button v-else-if="!(scope.row.success || scope.row.error || scope.row.active)" type="text"
                               @click.prevent="scope.row.success || scope.row.error === 'compressing' ? false : $refs.upload.update(scope.row, {active: true})">
                        上传
                    </el-button>
                    <el-button
                            v-else-if="scope.row.error && scope.row.error !== 'compressing' && $refs.upload.features.html5"
                            type="text"
                            @click.prevent="$refs.upload.update(scope.row, {active: true, error: '', progress: '0.00'})">
                        重新上传
                    </el-button>
                    <el-button type="text" @click.prevent="handleRemoveFile(scope.row)">移除</el-button>
                </template>
            </el-table-column>
        </el-table>

        <el-dialog title="查询处理详情" :visible.sync="dealDetailsDialogVisible" width="80%">

            <el-tabs v-model="dealDetailActiveTab" @tab-click="handleDealTabClick">
                <el-tab-pane label="失败信息" :name="dealDetailTabs.error">
                    <el-table height="260" :data="detailsGridData.error">
                        <el-table-column :property="column.prop" :label="column.prop" v-for="column in detailsGridColumn.error"></el-table-column>
                    </el-table>
                    <el-pagination
                            :page-size="200"
                            :pager-count="9"
                            layout="prev, pager, next"
                            :page-count="pagerConfig.error.count"
                            :current-page.sync="pagerConfig.error.page"
                            @current-change="handleDealPagerChange(dataSign.error)">
                    </el-pagination>
                </el-tab-pane>
                <el-tab-pane label="成功信息" :name="dealDetailTabs.success">
                    <el-table height="260" :data="detailsGridData.success">
                        <el-table-column :property="column.prop" :label="column.prop" v-for="column in detailsGridColumn.success"></el-table-column>
                    </el-table>
                    <el-pagination
                            :page-size="200"
                            :pager-count="9"
                            layout="prev, pager, next"
                            :page-count="pagerConfig.success.count"
                            :current-page.sync="pagerConfig.success.page"
                            @current-change="handleDealPagerChange(dataSign.success)">
                    </el-pagination>
                </el-tab-pane>

            </el-tabs>
            <!--<el-row>-->
                <!--<el-card>-->
                    <!--<div slot="header" class="clearfix">-->
                        <!--<span>成功信息</span>-->
                    <!--</div>-->
                    <!--<el-table height="260" :data="detailsGridData.success">-->
                        <!--<el-table-column :property="column.prop" :label="column.prop" v-for="column in detailsGridColumn.success"></el-table-column>-->
                    <!--</el-table>-->
                <!--</el-card>-->
            <!--</el-row>-->
            <!--<el-row>-->
                <!--<el-card>-->
                    <!--<div slot="header" class="clearfix">-->
                        <!--<span>失败信息</span>-->
                    <!--</div>-->
                    <!--<el-table height="260" :data="detailsGridData.error">-->
                        <!--<el-table-column :property="column.prop" :label="column.prop" v-for="column in detailsGridColumn.error"></el-table-column>-->
                    <!--</el-table>-->
                <!--</el-card>-->
            <!--</el-row>-->
        </el-dialog>

        <el-dialog title="上传历史信息" :visible.sync="historyDialogVisible" width="70%">
            <file-import-history :access_token="access_token" :collection-data="collectionData" :data-sign="dataSign" @toDownload="toDownload"></file-import-history>
        </el-dialog>

        <el-dialog title="文件配置" :visible.sync="fileConfigDialogVisible" width="90%">
            <file-config :access_token="access_token"></file-config>
        </el-dialog>
    </div>
</template>

<script>

    import isPlainObject from 'lodash/isPlainObject'
    import socket from '../src-config/socket'
    import fileConfig from './fileConfig'
    import fileImportHistory from './fileImportHistory'

    const steps = {
        '0':'开始',
        '1':'读取数据',
        '2':'检查数据',
        '3':'处理数据',
        '4':'存储数据',
        '5':'完成'
    }

    const YESORNO = {
        '0':'否',
        '1':'是',
    }

    export default {
        name: "fileImport",
        inject:['reload'],
        components:{fileConfig,fileImportHistory},
        data() {
            const access_token = 'access_token_' + Math.random();
            return {
                //请求标识
                access_token:access_token,
                //码值
                collectionData:{
                    steps,
                    YESORNO
                },
                //上传配置
                uploadConfig: {
                    files: [],
                    data:{"dto['access_token']": access_token},
                    // accept: 'image/png,image/gif,image/jpeg,image/webp',
                    extensions: /\.(xls|xlsx|csv|txt)$/i,
                    multiple: true,
                    directory: false,
                    drop: true,
                    dropDirectory: true,
                    addIndex: false,
                    thread: 10,
                    name: 'theFIFile',
                    postAction: this.Base.API + '/fileImport/fileImportController!upload.do',
                    uploadAuto: false,
                    isOption: false,
                },
                //当前监听对象
                expandRowkeys: [],
                expandedRows: [],
                rowKey: 'name',
                socketData: {
                    stepActive: 0,
                    total: 0,
                    progress: 0.00,
                    success: 0,
                    successNum: 0,
                    error: 0,
                    errorNum: 0,
                    wait: 0,
                    waitNum: 0,
                },
                //页内缓存
                socketDataCache: {},//实时监听数据缓存
                dealOverDataCache: [],//实时处理数据缓存

                //处理详情窗口
                dealDetailsDialogVisible:false,
                dealDetailTabs:{
                  success:"successTab",
                  error:"errorTab"
                },
                dealDetailActiveTab:"errorTab",
                detailsGridColumn:{
                    success:[],
                    error:[]
                },
                detailsGridData:{
                    success:[],
                    error:[]
                },
                detailsFile:{},
                dataSign:{
                  success:'1',
                  error:'2'
                },
                pagerConfig:{
                    success:{
                        count:1,
                        page:1,
                    },
                    error:{
                        count:1,
                        page:1,
                    }
                },

                //历史查询窗口
                historyDialogVisible:false,

                //文件配置管理窗口
                fileConfigDialogVisible:false,


            }
        },
        mounted() {
            this.initListenSocket();
        },
        methods: {
            initListenSocket() {
                socket.initListenSocket(this, ()=>{
                    let seeFile = this.expandedRows[0];
                    return {
                        access_token: this.access_token,
                        file_name : seeFile && seeFile.name || ''
                    };
                }, (key)=>{
                    if(this.dealOverDataCache.indexOf(key.file_name) > -1) return true;
                    return this.uploadConfig.files.length == 0 || this.expandRowkeys.length == 0
                },this.socketCall)
            },
            socketCall(content) {
                if(content == null)return;
                let key = this.expandRowkeys[0];
                this.socketDataCache[key] = content;

                //处理完成的数据标记缓存
                if(content.hasOwnProperty('end')){
                    this.dealOverDataCache.push(key)
                }
                this.socketDeal(content)
            },
            socketDeal(content) {
                if (!isPlainObject(content)) return;
                if (content.hasOwnProperty("step")) {
                    //步骤信息
                    this.setStep(content);
                }
                if (content.hasOwnProperty("size") > 0) {
                    //处理详情信息
                    this.setProgress(content);
                }
            },
            setStep(content) {
                this.socketData.stepActive = content.step
            },
            setProgress(content) {
                this.socketData.total = content.size;
                this.socketData.successNum = content.num1 || 0;
                this.socketData.success = Math.trunc(this.socketData.successNum/content.size * 100);
                this.socketData.errorNum = content.num2 || 0;
                this.socketData.error = Math.trunc(this.socketData.errorNum/content.size * 100);
                this.socketData.waitNum = content.size - content.num1 - content.num2;
                this.socketData.wait = Math.trunc(this.socketData.waitNum/content.size * 100);
                this.socketData.progress = Math.trunc((content.num1 + content.num2) / content.size * 100);
            },
            handleSelectFolader(){
                if (!this.$refs.upload.features.directory) {
                    this.alert('您的浏览器并不支持文件夹选择')
                    return
                }
                let input = this.$refs.upload.$el.querySelector('input')
                input.directory = true
                input.webkitdirectory = true
                this.uploadConfig.directory = true
                input.onclick = null
                input.click()
                input.onclick = (e) => {
                    this.uploadConfig.directory = false
                    input.directory = false
                    input.webkitdirectory = false
                }
            },
            /**
             * Has changed
             * @param  Object|undefined   newFile   只读
             * @param  Object|undefined   oldFile   只读
             * @return undefined
             */
            inputFile: function (newFile, oldFile) {

                if (newFile && oldFile && !newFile.active && oldFile.active) {
                    // 获得相应数据
                    console.log('response', newFile.response)
                    if (newFile.xhr) {
                        //  获得响应状态码
                        console.log('status', newFile.xhr.status)
                    }
                }
            },
            /**
             * Pretreatment
             * @param  Object|undefined   newFile   读写
             * @param  Object|undefined   oldFile   只读
             * @param  Function           prevent   阻止回调
             * @return undefined
             */
            inputFilter: function (newFile, oldFile, prevent) {
                //add 剔除不一样的格式数据
                if (newFile && !oldFile) {
                    if (!this.uploadConfig.extensions.test(newFile.name)) {
                        return prevent()
                    }
                    let index = this.uploadConfig.files.findIndex(item => item.name == newFile.name)
                    if(index > -1)  return prevent()
                }
                console.log(this.uploadConfig.files)
            },
            clearDataCache(file){
                let key = this.rowKey
                this.dealOverDataCache = this.dealOverDataCache.filter(item => item != file.name)
                this.expandRowkeys = this.expandRowkeys.filter(item => item != file.name)
                this.expandedRows = this.expandedRows.filter(item => item.name != file.name)
                delete this.socketDataCache[file[key]]
            },
            handleRemoveFile(file) {
                this.$refs.upload.remove(file);

                this.clearDataCache(file);
            },
            handleExpandChange(row, expandedRows) {
                //控制展开一项
                let rowKey = this.rowKey;
                if (expandedRows.indexOf(row) > -1)
                {
                    this.expandRowkeys = [row[rowKey]]
                    this.expandedRows = [row];
                }
                else
                    this.expandRowkeys = []

                if (this.expandRowkeys.length == 1) {
                    let key = this.expandRowkeys[0]
                    this.resetSocketData()
                    this.socketDeal(this.socketDataCache[key])
                }
            },
            resetSocketData(){
                this.socketData = {
                    stepActive: 0,
                    total: 0,
                    progress: 0.00,
                    success: 0,
                    successNum: 0,
                    error: 0,
                    errorNum: 0,
                    wait: 0,
                    waitNum: 0,
                }
            },
            toDownload(key,dataSign,name){
                name = name || '导出数据.xls'
                let nameOnly = name.substring(0,name.lastIndexOf("."))
                let exe = name.substring(name.lastIndexOf("."))
                if(this.dataSign.error == dataSign){
                    name = nameOnly + "__失败数据" + exe
                }else{
                    name = nameOnly + "__成功数据" + exe
                }
                // window.location.href=this.Base.API+"/fileImport/fileImportController!exportFileList.do?dto['access_token']="+key+"&dto['dataSign']="+dataSign

                const loading = this.$loading({
                    lock: true,
                    text: 'Loading',
                    spinner: 'el-icon-loading',
                    background: 'rgba(0, 0, 0, 0.7)'
                });
                this.Base.submit(this,key,{
                    url:'/fileImport/fileImportController!exportFileList.do',
                    formData:{
                        dataSign
                    },
                    responseType:'blob',
                },(data)=>{
                    let blob = new Blob([data])
                    let downloadElement = document.createElement('a');
                    let href = window.URL.createObjectURL(blob); //创建下载的链接
                    downloadElement.href = href;
                    downloadElement.download = name; //下载后文件名
                    document.body.appendChild(downloadElement);
                    downloadElement.click(); //点击下载
                    document.body.removeChild(downloadElement); //下载完成移除元素
                    window.URL.revokeObjectURL(href); //释放掉blob对象
                    loading.close();
                },(error)=>{
                    loading.close();
                    this.$message({
                        message: error,
                        type: 'error'
                    });
                })
            },
            handleDownloadInfo(row,dataSign){
                this.toDownload(this.access_token+row.name,dataSign,row.name)
            },
            handleSeeDealDetail(row){
                this.dealDetailActiveTab = this.dealDetailTabs.error
                this.dealDetailsDialogVisible = true;
                this.detailsFile = row
                this.detailsGridColumn.error = []
                this.detailsGridColumn.success = []
                this.detailsGridData.error = [];
                this.detailsGridData.success = [];
                this.pagerConfig = {
                    success:{
                        count:1,
                        page:1,
                    },
                    error:{
                        count:1,
                        page:1,
                    }
                }
                this.handleDealDetailQuery(this.dataSign.error,this.pagerConfig.error.page)
            },
            handleDealTabClick(tab){
                if(tab.name == this.dealDetailTabs.error){
                    if(this.detailsGridData.error.length == 0)
                        this.handleDealDetailQuery(this.dataSign.error,this.pagerConfig.error.page)
                }else{
                    if(this.detailsGridData.success.length == 0)
                        this.handleDealDetailQuery(this.dataSign.success,this.pagerConfig.success.page)
                }
            },
            handleDealPagerChange(dataSign){
                if(this.dataSign.error == dataSign){
                    this.handleDealDetailQuery(dataSign,this.pagerConfig.error.page)
                }else{
                    this.handleDealDetailQuery(dataSign,this.pagerConfig.success.page)
                }
            },
            handleDealDetailQuery(dataSign,page){
                let formData = {
                    dataSign:dataSign,
                    page:page
                }
                this.Base.submit(this,this.access_token+this.detailsFile.name,{
                    url:'/fileImport/fileImportController!getFileHandlerList.do',
                    formData
                },(data)=>{
                    let fields = data.fields || []
                    let list = data.list || []
                    let pageCount = data.pageCount || 1

                    if(this.dataSign.error == dataSign){
                        if(fields.length > 0 && this.detailsGridColumn.error.length == 0){
                            fields.split(",").forEach(item => {
                                this.detailsGridColumn.error.push({
                                    prop:item
                                })
                            })
                        }


                        this.detailsGridData.error = list;
                        this.pagerConfig.error.count=pageCount
                    }else{
                        if(fields.length > 0 && this.detailsGridColumn.success.length == 0){
                            fields.split(",").forEach(item => {
                                this.detailsGridColumn.success.push({
                                    prop:item
                                })
                            })
                        }

                        this.detailsGridData.success = list;
                        this.pagerConfig.success.count=pageCount
                    }
                },(error)=>{
                    console.log("view details error",error)
                })
            }
        }
    }
</script>
<style>
    .btn-file-upload label {
        cursor: pointer
    }

    .drop-active {
        top: 0;
        bottom: 0;
        right: 0;
        left: 0;
        position: fixed;
        z-index: 9999;
        opacity: .6;
        text-align: center;
        background: #000;
    }

    .drop-active h3 {
        margin: -.5em 0 0;
        position: absolute;
        top: 50%;
        left: 0;
        right: 0;
        -webkit-transform: translateY(-50%);
        -ms-transform: translateY(-50%);
        transform: translateY(-50%);
        font-size: 40px;
        color: #fff;
        padding: 0;
    }

    .top-container {
        padding: 10px;
    }

    .detail-context {
        margin-top: 10px;
    }

    .right-context {
        padding: 10px;
    }

    .right-context-row {
        margin-bottom: 20px;
    }
    .line{
        text-align: center;
    }
    .define-popover{
        height: 300px;
        overflow-y: auto;
        overflow-x: hidden;
    }
</style>